Smallest common region

Time: O(MxN); Space: O(N); medium

You are given some lists of regions where the first region of each list includes all other regions in that list.

Naturally, if a region X contains another region Y then X is bigger than Y. Also by definition a region X contains itself.

Given two regions region1, region2, find out the smallest region that contains both of them.

If you are given regions r1, r2 and r3 such that r1 includes r3, it is guaranteed there is no r2 such that r2 includes r3.

It’s guaranteed the smallest region exists.

Example 1:

                                  "Earth"
                        /                      \
           "North America"                  "South America"
       /                    \                  /
  "United States"           "Canada"       "Brazil"
  /            \            /      \
*"New York"*  "Boston"  "Ontario"  *"Quebec"*

Input: regions =

[
    ["Earth","North America","South America"],
    ["North America","United States","Canada"],
    ["United States","New York","Boston"],
    ["Canada","Ontario","Quebec"],
    ["South America","Brazil"]
],
region1 = "Quebec",
region2 = "New York"

Output: “North America”

Constraints:

  • 2 <= len(regions) <= 10^4

  • region1 != region2

  • All strings consist of English letters and spaces with at most 20 letters.

[9]:
class Solution1(object):
    """
    Time: O(M*N)
    Space: O(N)
    """
    def findSmallestRegion(self, regions, region1, region2):
        """
        :type regions: List[List[str]]
        :type region1: str
        :type region2: str
        :rtype: str
        """
        # parents = {}
        # for region in regions:
        #     for i in range(1, len(region)):
        #         parents[region[i]] = region[0]

        parents = {region[i] : region[0]
                   for region in regions
                   for i in range(1, len(region))
                  }

        lookup = {region1}

        while region1 in parents:
            region1 = parents[region1]
            lookup.add(region1)

        while region2 not in lookup:
            region2 = parents[region2]

        return region2
[10]:
s = Solution1()

regions = [
    ["Earth",         "North America", "South America"],
    ["North America", "United States", "Canada"],
    ["United States", "New York",      "Boston"],
    ["Canada",        "Ontario",       "Quebec"],
    ["South America", "Brazil"]
]
region1 = "Quebec"
region2 = "New York"
assert s.findSmallestRegion(regions, region1, region2) == "North America"